package com.belizer.demo.thread;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 线程安全的带缓存的因式分解器
 */
public class CachedFactorizer {
    private BigInteger lastNumber;
    private BigInteger[] lastFactors;
    private long hits;
    private long cacheHits;

    public synchronized long getHits() {
        return hits;
    }

    public synchronized double getCacheHitRatio() {
        return (double) (cacheHits / hits);
    }

    public BigInteger[] factor(BigInteger bi) {
        BigInteger[] factors = null;

        synchronized (this) {
            ++hits;
            if (bi.equals(lastNumber)) {
                ++cacheHits;
                factors = lastFactors.clone();
            }
        }

        if (Objects.isNull(factors)) {
            factors = doFactor(bi);
            synchronized (this) {
                lastNumber = bi;
                lastFactors = factors.clone();
            }
        }

        return factors;
    }

    // 因式分解逻辑
    private BigInteger[] doFactor(BigInteger bi) {
        List<BigInteger> factors = new ArrayList<>();
        BigInteger[] factorsArr = {};
        for (BigInteger i = new BigInteger("2"); i.compareTo(bi) <= 0; i = i.add(new BigInteger("1"))) {
            while (bi.remainder(i).equals(new BigInteger("0"))) {
                factors.add(i);
            }
        }
        return factors.toArray(factorsArr);
    }


}
